package juego.main;

import java.awt.BorderLayout;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.Iterator;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;


import juego.movimientos.*;
import juego.cosas.*;
import juego.graficos.*;
import juego.niveles.generator.*;
import juego.objetos.*;
import juego.roles.Mario;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/

/**
 * Esta clase modela la representacion grafica del juego, y maneja en parte, la logica 
 * del mismo.
 * @author Latini Macarena
 * @author Rosas Tifany.
 */
public class MainWin extends javax.swing.JFrame {

	{
		//Set Look & Feel
		try {
			javax.swing.UIManager.setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	private JScrollPane jScrollPane;
	private JPanel jPanel1;
	protected Mario mario;
	protected Nivel level;
	protected boolean control = false;
	protected MovimientoDerecha md;
	protected MovimientoIzquierda mi;
	protected MovimientoSaltar ms;
	protected boolean controlSalto = false;
	protected JLabel fondo;
	protected Thread h;


	/**
	* Auto-generated main method to display this JFrame
	*/
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				MainWin inst = new MainWin();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
				
				
			}
		});
	}
	
	/**
	 * Constructor
	 */
	public MainWin() {
		super();
		initGUI();
	}
	
	/**
	 * Se encarga de crear la parte de grafica del frame.
	 */
	private void initGUI() {
		try {
			JOptionPane.showMessageDialog(null,"El nivel del juego se carga mediante un archivo de texto. Debe elegir el archivo corresppondiente al nivel","Mensaje",JOptionPane.INFORMATION_MESSAGE);
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			this.setResizable(false);
			{
					jPanel1 = new JPanel();
					jPanel1.setLayout(new BorderLayout());
					jPanel1.setLayout(null);
					
					fondo= new JLabel();
					//Se crea la imagen de fondo
					fondo.setIcon(new ImageIcon(getClass().getClassLoader().getResource("juego/graficos/bloques/fondoNivel.gif")));
					fondo.setSize(9600,448);
					jPanel1.add(fondo);					
					jPanel1.setSize(9600, 448);
					jPanel1.setForeground(new java.awt.Color(0,255,255));
				}
			{
				jScrollPane = new JScrollPane(fondo,ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
				jPanel1.add(jScrollPane);
				getContentPane().add(jScrollPane, BorderLayout.CENTER);
				jScrollPane.setBackground(new java.awt.Color(0,255,255));
				jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
				jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
				jScrollPane.setOpaque(false);
				jScrollPane.getVerticalScrollBar().setForeground(new java.awt.Color(64,159,255));
				//Agregamos KeyListener al JScrollPane para simular el movimiento de la pantalla
				jScrollPane.addKeyListener(new KeyAdapter() {
					public void keyReleased(KeyEvent evt) {
						thisKeyReleased(evt);
					}
					public void keyPressed(KeyEvent evt) {
						thisKeyPressed(evt);
					}
				
				});
				
			}
			
			this.addKeyListener(new KeyAdapter() {
				public void keyReleased(KeyEvent evt) {
					thisKeyReleased(evt);
				}
				public void keyPressed(KeyEvent evt) {
					thisKeyPressed(evt);
				}
			
			});
			

			//Apaga el hilo de la gravedad en caso de cerrar la ventana
			this.addWindowListener(new WindowAdapter(){
				public void windowClosing(WindowEvent we){
					if(h!=null)
					{
						h.stop();
					}
					System.exit(0);
				}
			});
				
			pack();
			this.setSize(728, 456);
			this.setTitle("Mario Bros - Level 1");
			loadLevel();
			
		} catch (Exception e) {
		    //add your error handling code here
			e.printStackTrace();
		}
	}
	
	/**
	 * Permite que el usuario elija el archivo correspondiente al 
	 * nivel que desea jugar.
	 */
	private void loadLevel()
	{
		JFileChooser fc = new JFileChooser("./levels/");
		fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		int returnVal = fc.showOpenDialog(null);
		File f = fc.getSelectedFile();
		//Verificamos que se haya elegido un archivo
		if(f!=null)
		{
			CreatorByFile cbf = new CreatorByFile(f);
			level = cbf.getLevel();
			loadGraphicLevel( level );
		}
		else
		{
			System.exit(0);
		}
		
	}
	
	/**
	 * Dibuja el nivel. Carga todos los elementos del nivel y a Mario Bros
	 * @param level Nivel a cargar
	 */
	private void loadGraphicLevel( Nivel level )
	{
		Iterator <Objeto> itObjetos=level.obtenerListaBloques().iterator();
		int x, y;
		//Dibuja los bloques
		while(itObjetos.hasNext())
		{
			Objeto o=itObjetos.next();
			ElementoGrafico eg = o.getGrafico();
			x=o.getPosicion().getX();
			y=o.getPosicion().getY();
			eg.setLocation(x*32, y*32);
			this.fondo.add(eg);		
		}
		
		//Dibuja la llegada
		Llegada l=level.obtenerLlegada();
		if(l!=null)
		{
			ElementoGrafico elemg=l.getGrafico();
			int posx=l.getPosicion().getX();
			int posy=l.getPosicion().getY();
			elemg.setLocation(posx*32,posy*32);
			JLabel lleg= new JLabel();
			lleg.setIcon(new ImageIcon(getClass().getClassLoader().getResource("juego/graficos/bloques/cartel.gif")));
			elemg.setSize(113,107);
			fondo.add(elemg);
		}
		
		//Dibujo Mario 
		Posicion pos=new Posicion(7,5);	
		mario=new Mario(pos,level);
		ElementoGrafico eg = mario.getGrafico();
		eg.setLayout(null);
		x=mario.getPosicion().getX();
		y=mario.getPosicion().getY();
		eg.setLocation(x*32,y*64);
		
		Gravedad g= new Gravedad(level,mario,this);
		mario.setGravedad(g);
		eg.setVisible(true);
		this.fondo.add(eg);	
		//comienza el hilo de la gravedad
		this.h=new Thread(this.mario.getGravedad());
		h.start();
	}	
	
	/**
	 * Maneja los eventos del teclado
	 * @param evt Evento del teclado
	 */
	private void thisKeyPressed(KeyEvent evt) {
		if (!control)
		{
			if(mario.vive())
			{
				switch(evt.getKeyCode()){
					case KeyEvent.VK_UP: 
					{
						mario.saltar();
						control=false;
						ms= new MovimientoSaltar(mario,this,level);
						ms.start();
						break;
					}
					case KeyEvent.VK_RIGHT:
					{
						mario.derecha();
						md = new MovimientoDerecha(mario,level,jScrollPane,this);
						md.start();
						control = true;
						break;
					}
					case KeyEvent.VK_LEFT:
					{
						mario.izquierda();
						mi = new MovimientoIzquierda(mario,level,jScrollPane);
						mi.start();
						control = true;
						break;
					}	
					case KeyEvent.VK_DOWN:
					{
						mario.agachar();
					}
				}
			}
			else
			{
				h.stop();
			}
		}
	}
	
	/**
	 * Metodo auxiliar que controla si Mario esta saltando o no.
	 * @param b Verdadero si Mario esta saltando, falso en caso contrario.
	 */
	public void setControlSalto(boolean b)
	{
		controlSalto=b;
	}
	
	/**
	 * Metodo auxiliar que devuelve si Mario se encuentra saltando o no.
	 * @return Verdadero si Mario esta saltando, falso en caso contrario.
	 */
	public boolean estaSaltando()
	{
		return controlSalto;
	}

	private void thisKeyReleased(KeyEvent evt) {
		if(mario.vive())
		{
			this.control = false;
			mario.nada();
			if( md!=null)
			{
				md.stop();
			}
			if( mi!=null)
			{
				mi.stop();
			}
			if(evt.getKeyCode() != KeyEvent.VK_UP)
			{	
				if( md!=null)
					md.stop();
				if(mi!=null)
					mi.stop();
					
			}
		}
		
	}
	
	/**
	 * Termina la partida, por ende se paran los hilos de los movimientos.
	 */
	public void finPartida()
	{
		if( md!=null)
			md.stop();
		if(mi!=null)
			mi.stop();
	}

}
